//Import all needed packages
package com.gmail.viktor.yuryev;

import com.gmail.viktor.yuryev.model.Link;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileUtils {

    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH_mm_ss_dd_MM_yy");

    private HashMap<String, String> filteredFilesAndSourceFolders;
    private List<String> folderUploadFrom;
    //TODO Change me
    private String tempFolder = "C:\\temp2";
    private List<Link> mapping;

    public FileUtils(List<String> sourceFolders, List<Link> mapping) {
        this.folderUploadFrom = new ArrayList<String>();
        for (String sourceFolder : sourceFolders) {
            this.folderUploadFrom.add(removeLastSlash(sourceFolder));
        }
        filteredFilesAndSourceFolders = new HashMap<String,String>(100);
        this.mapping = mapping;
    }

    private String removeLastSlash(String sourceFolder) {
        return sourceFolder.endsWith(File.separator) ? sourceFolder.substring(0, sourceFolder.length() - 1) : sourceFolder;
    }

    public String zipIt() {
        String zipFile = tempFolder + File.separator + generateName() + ".zip";
        zipIt(zipFile);
        return zipFile;
    }

    public void zipIt(String zipFile) {
        byte[] buffer = new byte[1024];
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(fos);

            System.out.println("Output to Zip : " + zipFile);
            FileInputStream in = null;

            for (String file : filteredFilesAndSourceFolders.keySet()) {
                System.out.println("File Added : " + file);
                ZipEntry ze = new ZipEntry(file);
                zos.putNextEntry(ze);
                try {
                    in = new FileInputStream(filteredFilesAndSourceFolders.get(file) + File.separator + file);
                    int len;
                    while ((len = in.read(buffer)) > 0) {
                        zos.write(buffer, 0, len);
                    }
                }catch (Exception e){
                    System.out.println(e);
                }
                finally {
                    in.close();
                }
            }

            zos.closeEntry();
            System.out.println("Folder successfully compressed");

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                zos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public HashMap<String, String> generateFileList() {
        for (String sourceFolder : folderUploadFrom) {
            generateFileList(new File(sourceFolder));
        }
        return filteredFilesAndSourceFolders;
    }

    private Path getFolderInMapping(Path file) {
        for (Link localFile : mapping) {
            if (file.startsWith(localFile.getLocalFolder()))
                return localFile.getLocalFolder();
        }
        return null;

    }

    private void generateFileList(File node) {
        Path folderInMapping = getFolderInMapping(node.toPath());
        if (folderInMapping == null)
            return;
        // add file only
        if (node.isFile()) {
            Path relativePath = folderInMapping.relativize(node.toPath());
            filteredFilesAndSourceFolders.put(relativePath.toString(), folderInMapping.toString());
        } else {
            String[] subNote = node.list();
            for (String filename : subNote) {
                generateFileList(new File(node, filename));
            }
        }
    }



    public static String generateName() {
        return "temp_" + DATE_FORMAT.format(new Date());
    }
}    